home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / InstrList.c < prev    next >
Text File  |  1994-08-15  |  24KB  |  832 lines

  1. /* InstrList.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "InstrList.h"
  31. #include "StringList.h"
  32. #include "Array.h"
  33. #include "Memory.h"
  34. #include "Alert.h"
  35. #include "DataMunging.h"
  36. #include "InstrObject.h"
  37. #include "BufferedFileInput.h"
  38. #include "BufferedFileOutput.h"
  39. #include "Files.h"
  40. #include "Scrap.h"
  41.  
  42.  
  43. struct InstrListRec
  44.     {
  45.         StringListRec*                    List;
  46.         struct CodeCenterRec*        CodeCenter;
  47.         struct MainWindowRec*        MainWindow;
  48.         ArrayRec*                                InstrArray;
  49.         MyBoolean                                InstrListChanged;
  50.     };
  51.  
  52.  
  53. #define MAGICSCRAPSTRING ("\xff\x00\x1f\xfe InstrumentObjectScrap")
  54.  
  55.  
  56. /* create a new instrument list */
  57. InstrListRec*                NewInstrList(struct MainWindowRec* MainWindow,
  58.                                             struct CodeCenterRec* CodeCenter, WinType* ScreenID,
  59.                                             OrdType XLoc, OrdType YLoc, OrdType Width, OrdType Height)
  60.     {
  61.         InstrListRec*            InstrList;
  62.  
  63.         InstrList = (InstrListRec*)AllocPtrCanFail(sizeof(InstrListRec),"InstrListRec");
  64.         if (InstrList == NIL)
  65.             {
  66.              FailurePoint1:
  67.                 return NIL;
  68.             }
  69.         InstrList->InstrArray = NewArray();
  70.         if (InstrList->InstrArray == NIL)
  71.             {
  72.              FailurePoint2:
  73.                 ReleasePtr((char*)InstrList);
  74.                 goto FailurePoint1;
  75.             }
  76.         InstrList->List = NewStringList(ScreenID,XLoc,YLoc,Width,Height,
  77.             GetScreenFont(),9,StringListDontAllowMultipleSelection,"Instruments");
  78.         if (InstrList->List == NIL)
  79.             {
  80.              FailurePoint3:
  81.                 DisposeArray(InstrList->InstrArray);
  82.                 goto FailurePoint2;
  83.             }
  84.         InstrList->CodeCenter = CodeCenter;
  85.         InstrList->MainWindow = MainWindow;
  86.         InstrList->InstrListChanged = False;
  87.         return InstrList;
  88.     }
  89.  
  90.  
  91. /* delete the instrument list and all of the instruments it contains */
  92. void                                DisposeInstrList(InstrListRec* InstrList)
  93.     {
  94.         long                            Scan;
  95.         long                            Limit;
  96.  
  97.         CheckPtrExistence(InstrList);
  98.         Limit = ArrayGetLength(InstrList->InstrArray);
  99.         for (Scan = 0; Scan < Limit; Scan += 1)
  100.             {
  101.                 InstrObjectRec*        InstrTemp;
  102.  
  103.                 InstrTemp = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  104.                 DisposeInstrObject(InstrTemp);
  105.             }
  106.         DisposeArray(InstrList->InstrArray);
  107.         DisposeStringList(InstrList->List);
  108.         ReleasePtr((char*)InstrList);
  109.     }
  110.  
  111.  
  112. /* change the location of the instrument list in the window */
  113. void                                SetInstrListLocation(InstrListRec* InstrList,
  114.                                             OrdType XLoc, OrdType YLoc, OrdType Width, OrdType Height)
  115.     {
  116.         CheckPtrExistence(InstrList);
  117.         SetStringListLoc(InstrList->List,XLoc,YLoc,Width,Height);
  118.     }
  119.  
  120.  
  121. /* redraw the list */
  122. void                                InstrListRedraw(InstrListRec* InstrList)
  123.     {
  124.         CheckPtrExistence(InstrList);
  125.         RedrawStringList(InstrList->List);
  126.     }
  127.  
  128.  
  129. /* see if the specified coordinates falls inside the instrument list rectangle */
  130. MyBoolean                        InstrListHitTest(InstrListRec* InstrList,
  131.                                             OrdType XLoc, OrdType YLoc)
  132.     {
  133.         CheckPtrExistence(InstrList);
  134.         return StringListHitTest(InstrList->List,XLoc,YLoc);
  135.     }
  136.  
  137.  
  138. /* handle a mouse down event for the instrument list */
  139. void                                InstrListDoMouseDown(InstrListRec* InstrList,
  140.                                             OrdType XLoc, OrdType YLoc, ModifierFlags Modifiers)
  141.     {
  142.         CheckPtrExistence(InstrList);
  143.         if (StringListMouseDown(InstrList->List,XLoc,YLoc,Modifiers))
  144.             {
  145.                 /* if it returns true, then it was a double click */
  146.                 InstrListOpenSelection(InstrList);
  147.             }
  148.     }
  149.  
  150.  
  151. /* called when the window becomes active */
  152. void                                InstrListBecomeActive(InstrListRec* InstrList)
  153.     {
  154.         CheckPtrExistence(InstrList);
  155.         EnableStringList(InstrList->List);
  156.     }
  157.  
  158.  
  159. /* called when the window becomes inactive */
  160. void                                InstrListBecomeInactive(InstrListRec* InstrList)
  161.     {
  162.         CheckPtrExistence(InstrList);
  163.         DisableStringList(InstrList->List);
  164.     }
  165.  
  166.  
  167. /* called when a selection is made in another list, so that this list */
  168. /* is deselected */
  169. void                                InstrListDeselect(InstrListRec* InstrList)
  170.     {
  171.         CheckPtrExistence(InstrList);
  172.         DeselectAllStringListElements(InstrList->List);
  173.     }
  174.  
  175.  
  176. /* check to see if there is a selection in this list */
  177. MyBoolean                        InstrListIsThereSelection(InstrListRec* InstrList)
  178.     {
  179.         CheckPtrExistence(InstrList);
  180.         return (GetStringListHowManySelectedItems(InstrList->List) > 0);
  181.     }
  182.  
  183.  
  184. /* check to see if any of the instruments contained in this list need to be saved */
  185. MyBoolean                        DoesInstrListNeedToBeSaved(InstrListRec* InstrList)
  186.     {
  187.         long                            Scan;
  188.         long                            Limit;
  189.         MyBoolean                    Flag;
  190.  
  191.         CheckPtrExistence(InstrList);
  192.         Flag = InstrList->InstrListChanged;
  193.         Limit = ArrayGetLength(InstrList->InstrArray);
  194.         for (Scan = 0; (Scan < Limit) && !Flag; Scan += 1)
  195.             {
  196.                 InstrObjectRec*        InstrTemp;
  197.  
  198.                 InstrTemp = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  199.                 if (HasInstrObjectBeenModified(InstrTemp))
  200.                     {
  201.                         Flag = True;
  202.                     }
  203.             }
  204.         return Flag;
  205.     }
  206.  
  207.  
  208. /* open an edit window for the selected instrument */
  209. void                                InstrListOpenSelection(InstrListRec* InstrList)
  210.     {
  211.         ArrayRec*                    ListOfSelections;
  212.  
  213.         CheckPtrExistence(InstrList);
  214.         ListOfSelections = GetListOfSelectedItems(InstrList->List);
  215.         if (ListOfSelections != NIL)
  216.             {
  217.                 long                            Scan;
  218.                 long                            Limit;
  219.  
  220.                 Limit = ArrayGetLength(ListOfSelections);
  221.                 for (Scan = 0; Scan < Limit; Scan += 1)
  222.                     {
  223.                         InstrObjectRec*        InstrTemp;
  224.  
  225.                         InstrTemp = (InstrObjectRec*)ArrayGetElement(ListOfSelections,Scan);
  226.                         InstrObjectOpenWindow(InstrTemp);
  227.                     }
  228.                 DisposeArray(ListOfSelections);
  229.             }
  230.     }
  231.  
  232.  
  233. /* create a new instrument and open a window for it */
  234. void                                InstrListNewInstr(InstrListRec* InstrList)
  235.     {
  236.         InstrObjectRec*        Instr;
  237.  
  238.         CheckPtrExistence(InstrList);
  239.         /* create the object */
  240.         Instr = NewInstrObject(InstrList->CodeCenter,InstrList->MainWindow,InstrList);
  241.         if (Instr == NIL)
  242.             {
  243.              FailurePoint1:
  244.                 AlertHalt("There is not enough memory available to create a new instrument.",NIL);
  245.                 return;
  246.             }
  247.         /* add it to the string list */
  248.         if (!InsertStringListElement(InstrList->List,NIL,NIL,Instr,True))
  249.             {
  250.              FailurePoint2:
  251.                 DisposeInstrObject(Instr);
  252.                 goto FailurePoint1;
  253.             }
  254.         MainWindowDeselectAllOtherStringLists(InstrList->MainWindow,InstrList);
  255.         SelectStringListElement(InstrList->List,Instr);
  256.         MakeStringListSelectionVisible(InstrList->List);
  257.         /* add it to the array */
  258.         if (!ArrayAppendElement(InstrList->InstrArray,Instr))
  259.             {
  260.              FailurePoint3:
  261.                 RemoveStringListElement(InstrList->List,Instr,True);
  262.                 goto FailurePoint2;
  263.             }
  264.         /* update our internal flags */
  265.         InstrList->InstrListChanged = True;
  266.         /* change the name in the list */
  267.         InstrListInstrNameChanged(InstrList,Instr);
  268.         /* show the window */
  269.         InstrObjectOpenWindow(Instr);
  270.     }
  271.  
  272.  
  273. /* delete the selected instrument */
  274. void                                InstrListDeleteSelection(InstrListRec* InstrList)
  275.     {
  276.         ArrayRec*                    ListOfSelections;
  277.  
  278.         CheckPtrExistence(InstrList);
  279.         ListOfSelections = GetListOfSelectedItems(InstrList->List);
  280.         if (ListOfSelections != NIL)
  281.             {
  282.                 long                                Scan;
  283.                 long                                Limit;
  284.  
  285.                 Limit = ArrayGetLength(ListOfSelections);
  286.                 for (Scan = 0; Scan < Limit; Scan += 1)
  287.                     {
  288.                         InstrObjectRec*            OneToZap;
  289.  
  290.                         OneToZap = (InstrObjectRec*)ArrayGetElement(ListOfSelections,Scan);
  291.                         InstrListDeleteInstr(InstrList,OneToZap);
  292.                     }
  293.                 DisposeArray(ListOfSelections);
  294.             }
  295.     }
  296.  
  297.  
  298. /* delete the explicitly specified instrument */
  299. void                                InstrListDeleteInstr(InstrListRec* InstrList,
  300.                                             struct InstrObjectRec* TheInstr)
  301.     {
  302.         long                                Scan;
  303.         long                                Limit;
  304.  
  305.         CheckPtrExistence(InstrList);
  306.         Limit = ArrayGetLength(InstrList->InstrArray);
  307.         for (Scan = 0; Scan < Limit; Scan += 1)
  308.             {
  309.                 InstrObjectRec*            InstrTemp;
  310.  
  311.                 InstrTemp = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  312.                 if (TheInstr == InstrTemp)
  313.                     {
  314.                         FileSpec*                    BackupFileWhere;
  315.                         FileType*                    BackupFile;
  316.                         MyBoolean                    Success = False;
  317.  
  318.                         BackupFileWhere = NewTempFileSpec(CODE4BYTES('?','?','?','?'),
  319.                             CODE4BYTES('?','?','?','?'));
  320.                         if (BackupFileWhere != NIL)
  321.                             {
  322.                                 if (OpenFile(BackupFileWhere,&BackupFile,eReadAndWrite))
  323.                                     {
  324.                                         BufferedOutputRec*    Output;
  325.  
  326.                                         Output = NewBufferedOutput(BackupFile);
  327.                                         if (Output != NIL)
  328.                                             {
  329.                                                 if (WriteBufferedOutput(Output,sizeof(MAGICSCRAPSTRING),
  330.                                                     MAGICSCRAPSTRING))
  331.                                                     {
  332.                                                         if (InstrObjectWriteDataOut(TheInstr,Output)
  333.                                                             == eFileLoadNoError)
  334.                                                             {
  335.                                                                 Success = True;
  336.                                                             }
  337.                                                     }
  338.                                                 if (!EndBufferedOutput(Output))
  339.                                                     {
  340.                                                         Success = False;
  341.                                                     }
  342.                                             }
  343.                                          else
  344.                                             {
  345.                                                 CloseFile(BackupFile);
  346.                                             }
  347.                                     }
  348.                                  else
  349.                                     {
  350.                                         DeleteFile(BackupFileWhere);
  351.                                         DisposeFileSpec(BackupFileWhere);
  352.                                     }
  353.                             }
  354.                         if (Success)
  355.                             {
  356.                                 MainWindowNewDeleteUndoInfo(InstrList->MainWindow,BackupFileWhere,
  357.                                     BackupFile);
  358.                                 DisposeInstrObject(InstrTemp);
  359.                                 RemoveStringListElement(InstrList->List,InstrTemp,True);
  360.                                 ArrayDeleteElement(InstrList->InstrArray,Scan);
  361.                                 InstrList->InstrListChanged = True;
  362.                             }
  363.                          else
  364.                             {
  365.                                 YesNoCancelType        Decision;
  366.  
  367.                                 Decision = AskYesNoCancel("Unable to save undo information for object.  "
  368.                                     "Delete object anyway?",NIL,"Delete","Cancel",NIL/*nothirdbutton*/);
  369.                                 if (Decision == eYes)
  370.                                     {
  371.                                         DisposeInstrObject(InstrTemp);
  372.                                         RemoveStringListElement(InstrList->List,InstrTemp,True);
  373.                                         ArrayDeleteElement(InstrList->InstrArray,Scan);
  374.                                         InstrList->InstrListChanged = True;
  375.                                     }
  376.                             }
  377.                         return;
  378.                     }
  379.             }
  380.         EXECUTE(PRERR(AllowResume,"InstrListDeleteInstr:  couldn't find object"));
  381.     }
  382.  
  383.  
  384. /* the name of an instrument has changed, so the name in the scrolling */
  385. /* list must also be changed */
  386. void                                InstrListInstrNameChanged(InstrListRec* InstrList,
  387.                                             struct InstrObjectRec* TheInstr)
  388.     {
  389.         char*                            InstrName;
  390.  
  391.         CheckPtrExistence(InstrList);
  392.         CheckPtrExistence(TheInstr);
  393.         ERROR(ArrayFindElement(InstrList->InstrArray,TheInstr) < 0,
  394.             PRERR(ForceAbort,"InstrListInstrNameChanged:  unknown instrument"));
  395.         InstrName = InstrObjectGetNameCopy(TheInstr);
  396.         if (InstrName != NIL)
  397.             {
  398.                 char*                            InstrNameNullTerminated;
  399.  
  400.                 InstrNameNullTerminated = BlockToStringCopy(InstrName);
  401.                 if (InstrNameNullTerminated != NIL)
  402.                     {
  403.                         ChangeStringListElementName(InstrList->List,
  404.                             InstrNameNullTerminated,TheInstr);
  405.                         ReleasePtr(InstrNameNullTerminated);
  406.                     }
  407.                 ReleasePtr(InstrName);
  408.             }
  409.     }
  410.  
  411.  
  412. /* look for a specified instrument.  returns NIL if not found.  the name is */
  413. /* NOT null terminated */
  414. struct InstrObjectRec*    InstrListLookupNamedInstr(InstrListRec* InstrList, char* Name)
  415.     {
  416.         long                            Scan;
  417.         long                            Limit;
  418.  
  419.         CheckPtrExistence(InstrList);
  420.         CheckPtrExistence(Name);
  421.         Limit = ArrayGetLength(InstrList->InstrArray);
  422.         for (Scan = 0; Scan < Limit; Scan += 1)
  423.             {
  424.                 InstrObjectRec*            Instr;
  425.                 char*                                NameCopy;
  426.  
  427.                 Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  428.                 NameCopy = InstrObjectGetNameCopy(Instr);
  429.                 if (NameCopy != NIL)
  430.                     {
  431.                         if (PtrSize(Name) == PtrSize(NameCopy))
  432.                             {
  433.                                 if (MemEqu(Name,NameCopy,PtrSize(Name)))
  434.                                     {
  435.                                         ReleasePtr(NameCopy);
  436.                                         return Instr;
  437.                                     }
  438.                             }
  439.                         ReleasePtr(NameCopy);
  440.                     }
  441.             }
  442.         return NIL;
  443.     }
  444.  
  445.  
  446. /* document's name has changed, so we need to update the windows */
  447. void                                InstrListGlobalNameChange(InstrListRec* InstrList,
  448.                                             char* NewFilename)
  449.     {
  450.         long                            Scan;
  451.         long                            Limit;
  452.  
  453.         CheckPtrExistence(InstrList);
  454.         Limit = ArrayGetLength(InstrList->InstrArray);
  455.         for (Scan = 0; Scan < Limit; Scan += 1)
  456.             {
  457.                 InstrObjectRec*            Instr;
  458.  
  459.                 Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  460.                 InstrObjectGlobalNameChange(Instr,NewFilename);
  461.             }
  462.     }
  463.  
  464.  
  465. /* compile all of the instruments definitions */
  466. MyBoolean                        InstrListMakeUpToDate(InstrListRec* InstrList)
  467.     {
  468.         long                            Scan;
  469.         long                            Limit;
  470.  
  471.         CheckPtrExistence(InstrList);
  472.         Limit = ArrayGetLength(InstrList->InstrArray);
  473.         for (Scan = 0; Scan < Limit; Scan += 1)
  474.             {
  475.                 InstrObjectRec*            Instr;
  476.  
  477.                 Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  478.                 if (!MakeInstrObjectUpToDate(Instr))
  479.                     {
  480.                         return False;
  481.                     }
  482.             }
  483.         return True;
  484.     }
  485.  
  486.  
  487. /* dispose of all of the objects from the instrument definitions */
  488. void                                InstrListUnbuildAll(InstrListRec* InstrList)
  489.     {
  490.         long                            Scan;
  491.         long                            Limit;
  492.  
  493.         CheckPtrExistence(InstrList);
  494.         Limit = ArrayGetLength(InstrList->InstrArray);
  495.         for (Scan = 0; Scan < Limit; Scan += 1)
  496.             {
  497.                 InstrObjectRec*            Instr;
  498.  
  499.                 Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  500.                 UnbuildInstrObject(Instr);
  501.             }
  502.     }
  503.  
  504.  
  505. /*   4-byte little endian number of instrument objects (positive 2s complement) */
  506. /*   n-byte data for the instrument objects */
  507.  
  508.  
  509. /* read instrument definitions from a file.  returns True if completely successful. */
  510. FileLoadingErrors        InstrListReadData(InstrListRec* InstrList,
  511.                                             struct BufferedInputRec* Input)
  512.     {
  513.         signed long                NumberOfObjects;
  514.         long                            Scan;
  515.  
  516.         CheckPtrExistence(InstrList);
  517.         CheckPtrExistence(Input);
  518.  
  519.         /*   4-byte little endian number of objects (positive 2s complement) */
  520.         if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfObjects))
  521.             {
  522.                 return eFileLoadDiskError;
  523.             }
  524.         if (NumberOfObjects < 0)
  525.             {
  526.                 return eFileLoadBadFormat;
  527.             }
  528.  
  529.         /*   n-byte data for the objects */
  530.         for (Scan = 0; Scan < NumberOfObjects; Scan += 1)
  531.             {
  532.                 InstrObjectRec*        Instr EXECUTE(= (InstrObjectRec*)0x81818181);
  533.                 FileLoadingErrors    Error;
  534.  
  535.                 /* load the object */
  536.                 Error = InstrObjectNewFromFile(&Instr,Input,InstrList->CodeCenter,
  537.                     InstrList->MainWindow,InstrList);
  538.                 if (Error != eFileLoadNoError)
  539.                     {
  540.                      FailurePoint1:
  541.                         return Error;
  542.                     }
  543.                 CheckPtrExistence(Instr);
  544.                 /* add it to the string list */
  545.                 if (!InsertStringListElement(InstrList->List,NIL,NIL,Instr,True))
  546.                     {
  547.                      FailurePoint2:
  548.                         DisposeInstrObject(Instr);
  549.                         Error = eFileLoadOutOfMemory;
  550.                         goto FailurePoint1;
  551.                     }
  552.                 /* add it to the array */
  553.                 if (!ArrayAppendElement(InstrList->InstrArray,Instr))
  554.                     {
  555.                      FailurePoint3:
  556.                         RemoveStringListElement(InstrList->List,Instr,True);
  557.                         goto FailurePoint2;
  558.                     }
  559.                 /* change the name in the list */
  560.                 InstrListInstrNameChanged(InstrList,Instr);
  561.             }
  562.  
  563.         return eFileLoadNoError;
  564.     }
  565.  
  566.  
  567. /* write instrument definitions to a file.  returns True if completely successful. */
  568. FileLoadingErrors        InstrListWriteData(InstrListRec* InstrList,
  569.                                             struct BufferedOutputRec* Output)
  570.     {
  571.         long                            NumberOfObjects;
  572.         long                            Scan;
  573.  
  574.         CheckPtrExistence(InstrList);
  575.         CheckPtrExistence(Output);
  576.  
  577.         /*   4-byte little endian number of objects (positive 2s complement) */
  578.         NumberOfObjects = ArrayGetLength(InstrList->InstrArray);
  579.         if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfObjects))
  580.             {
  581.                 return eFileLoadDiskError;
  582.             }
  583.  
  584.         /*   n-byte data for the objects */
  585.         for (Scan = 0; Scan < NumberOfObjects; Scan += 1)
  586.             {
  587.                 InstrObjectRec*            Instr;
  588.                 FileLoadingErrors        Error;
  589.  
  590.                 /* get the object */
  591.                 Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  592.                 /* write the object out */
  593.                 Error = InstrObjectWriteDataOut(Instr,Output);
  594.                 /* handle errors */
  595.                 if (Error != eFileLoadNoError)
  596.                     {
  597.                         return Error;
  598.                     }
  599.             }
  600.  
  601.         return eFileLoadNoError;
  602.     }
  603.  
  604.  
  605. /* after a file has been saved, this is called to mark all objects as not modified. */
  606. void                                InstrListMarkAllObjectsSaved(InstrListRec* InstrList)
  607.     {
  608.         long                            Scan;
  609.         long                            Limit;
  610.  
  611.         CheckPtrExistence(InstrList);
  612.         Limit = ArrayGetLength(InstrList->InstrArray);
  613.         for (Scan = 0; Scan < Limit; Scan += 1)
  614.             {
  615.                 InstrObjectRec*            Instr;
  616.  
  617.                 Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Scan);
  618.                 InstrObjectMarkAsSaved(Instr);
  619.             }
  620.         InstrList->InstrListChanged = False;
  621.     }
  622.  
  623.  
  624. /* copy the selected object in the list to the clipboard.  return False if failed. */
  625. MyBoolean                        InstrListCopyObject(InstrListRec* InstrList)
  626.     {
  627.         ArrayRec*                            ListOfSelections;
  628.         MyBoolean                            TotalSuccessFlag = False;
  629.  
  630.         CheckPtrExistence(InstrList);
  631.         ListOfSelections = GetListOfSelectedItems(InstrList->List);
  632.         if (ListOfSelections != NIL)
  633.             {
  634.                 if (ArrayGetLength(ListOfSelections) >= 1)
  635.                     {
  636.                         InstrObjectRec*            InstrTemp;
  637.                         FileSpec*                        TempFileLocation;
  638.  
  639.                         InstrTemp = (InstrObjectRec*)ArrayGetElement(ListOfSelections,0);
  640.                         /* open the temporary file */
  641.                         TempFileLocation = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
  642.                             CODE4BYTES('\?','\?','\?','\?'));
  643.                         if (TempFileLocation != NIL)
  644.                             {
  645.                                 FileType*                            FileDescriptor;
  646.  
  647.                                 if (OpenFile(TempFileLocation,&FileDescriptor,eReadAndWrite))
  648.                                     {
  649.                                         BufferedOutputRec*        BufferedFile;
  650.  
  651.                                         BufferedFile = NewBufferedOutput(FileDescriptor);
  652.                                         if (BufferedFile != NIL)
  653.                                             {
  654.                                                 MyBoolean                            WriteSucceeded = False;
  655.  
  656.                                                 if (WriteBufferedOutput(BufferedFile,sizeof(MAGICSCRAPSTRING),
  657.                                                     MAGICSCRAPSTRING))
  658.                                                     {
  659.                                                         if (InstrObjectWriteDataOut(InstrTemp,BufferedFile)
  660.                                                             == eFileLoadNoError)
  661.                                                             {
  662.                                                                 WriteSucceeded = True;
  663.                                                             }
  664.                                                     }
  665.                                                 if (EndBufferedOutput(BufferedFile) && WriteSucceeded)
  666.                                                     {
  667.                                                         char*                            Buffer;
  668.                                                         long                            NumberOfBytes;
  669.  
  670.                                                         NumberOfBytes = GetFileLength(FileDescriptor);
  671.                                                         Buffer = AllocPtrCanFail(NumberOfBytes,
  672.                                                             "InstrListCopyObject:  scrap buffer");
  673.                                                         if (Buffer != NIL)
  674.                                                             {
  675.                                                                 if (SetFilePosition(FileDescriptor,0))
  676.                                                                     {
  677.                                                                         if (0 == ReadFromFile(FileDescriptor,
  678.                                                                             Buffer,NumberOfBytes))
  679.                                                                             {
  680.                                                                                 if (SetScrapToThis(Buffer))
  681.                                                                                     {
  682.                                                                                         TotalSuccessFlag = True;
  683.                                                                                     }
  684.                                                                             }
  685.                                                                     }
  686.                                                                 ReleasePtr(Buffer);
  687.                                                             }
  688.                                                     }
  689.                                             }
  690.                                         CloseFile(FileDescriptor);
  691.                                     }
  692.                                 DeleteFile(TempFileLocation);
  693.                                 DisposeFileSpec(TempFileLocation);
  694.                             }
  695.                     }
  696.                 DisposeArray(ListOfSelections);
  697.             }
  698.         return TotalSuccessFlag;
  699.     }
  700.  
  701.  
  702. /* try to paste the clipboard in as an instrument.  returns False if it failed or the */
  703. /* clipboard did not contain an instrument. */
  704. MyBoolean                        InstrListPasteObject(InstrListRec* InstrList)
  705.     {
  706.         MyBoolean                    TotalSuccessFlag = False;
  707.         char*                            Scrap;
  708.  
  709.         CheckPtrExistence(InstrList);
  710.         Scrap = GetCopyOfScrap();
  711.         if (Scrap != NIL)
  712.             {
  713.                 FileSpec*                    TempFileLocation;
  714.  
  715.                 TempFileLocation = NewTempFileSpec(CODE4BYTES('\?','\?','\?','\?'),
  716.                     CODE4BYTES('\?','\?','\?','\?'));
  717.                 if (TempFileLocation != NIL)
  718.                     {
  719.                         FileType*                            FileDescriptor;
  720.  
  721.                         if (OpenFile(TempFileLocation,&FileDescriptor,eReadAndWrite))
  722.                             {
  723.                                 BufferedOutputRec*        BufferedFile;
  724.  
  725.                                 BufferedFile = NewBufferedOutput(FileDescriptor);
  726.                                 if (BufferedFile != NIL)
  727.                                     {
  728.                                         MyBoolean                            WriteSucceeded = False;
  729.  
  730.                                         if (WriteBufferedOutput(BufferedFile,PtrSize(Scrap),Scrap))
  731.                                             {
  732.                                                 WriteSucceeded = True;
  733.                                             }
  734.                                         if (EndBufferedOutput(BufferedFile) && WriteSucceeded)
  735.                                             {
  736.                                                 TotalSuccessFlag = InstrListPasteFromFile(InstrList,
  737.                                                     FileDescriptor);
  738.                                             }
  739.                                     }
  740.                                 CloseFile(FileDescriptor);
  741.                             }
  742.                         DeleteFile(TempFileLocation);
  743.                         DisposeFileSpec(TempFileLocation);
  744.                     }
  745.                 ReleasePtr(Scrap);
  746.             }
  747.         return TotalSuccessFlag;
  748.     }
  749.  
  750.  
  751. /* try to paste the instrument object in from the file */
  752. MyBoolean                        InstrListPasteFromFile(InstrListRec* InstrList,
  753.                                             struct FileType* File)
  754.     {
  755.         MyBoolean                    TotalSuccessFlag = False;
  756.  
  757.         CheckPtrExistence(InstrList);
  758.         if (SetFilePosition(File,0))
  759.             {
  760.                 BufferedInputRec*    InputFile;
  761.  
  762.                 InputFile = NewBufferedInput(File);
  763.                 if (InputFile != NIL)
  764.                     {
  765.                         char                            HeaderTest[sizeof(MAGICSCRAPSTRING)];
  766.  
  767.                         if (ReadBufferedInput(InputFile,sizeof(MAGICSCRAPSTRING),HeaderTest))
  768.                             {
  769.                                 if (MemEqu(MAGICSCRAPSTRING,HeaderTest,sizeof(MAGICSCRAPSTRING)))
  770.                                     {
  771.                                         InstrObjectRec*                InstrTemp EXECUTE(= (InstrObjectRec*)0x81818181);
  772.  
  773.                                         if (eFileLoadNoError == InstrObjectNewFromFile(&InstrTemp,InputFile,
  774.                                             InstrList->CodeCenter,InstrList->MainWindow,InstrList))
  775.                                             {
  776.                                                 CheckPtrExistence(InstrTemp);
  777.                                                 /* add it to the scrolling object list */
  778.                                                 if (!InsertStringListElement(InstrList->List,NIL,NIL,InstrTemp,True))
  779.                                                     {
  780.                                                      FailurePoint:
  781.                                                         DisposeInstrObject(InstrTemp);
  782.                                                     }
  783.                                                  else
  784.                                                     {
  785.                                                         MainWindowDeselectAllOtherStringLists(InstrList->MainWindow,InstrList);
  786.                                                         SelectStringListElement(InstrList->List,InstrTemp);
  787.                                                         MakeStringListSelectionVisible(InstrList->List);
  788.                                                         /* add it to the array */
  789.                                                         if (!ArrayAppendElement(InstrList->InstrArray,InstrTemp))
  790.                                                             {
  791.                                                                 RemoveStringListElement(InstrList->List,InstrTemp,True);
  792.                                                                 goto FailurePoint;
  793.                                                             }
  794.                                                          else
  795.                                                             {
  796.                                                                 /* change the name in the list */
  797.                                                                 InstrListInstrNameChanged(InstrList,InstrTemp);
  798.                                                                 TotalSuccessFlag = True;
  799.                                                                 InstrList->InstrListChanged = True;
  800.                                                             }
  801.                                                     }
  802.                                             }
  803.                                     }
  804.                             }
  805.                         EndBufferedInput(InputFile);
  806.                     }
  807.             }
  808.         return TotalSuccessFlag;
  809.     }
  810.  
  811.  
  812. /* find out how many instruments there are in this list */
  813. long                                InstrListHowMany(InstrListRec* InstrList)
  814.     {
  815.         CheckPtrExistence(InstrList);
  816.         return ArrayGetLength(InstrList->InstrArray);
  817.     }
  818.  
  819.  
  820. /* get an indexed instruments from the list */
  821. struct InstrObjectRec*    InstrListGetIndexedInstr(InstrListRec* InstrList, long Index)
  822.     {
  823.         InstrObjectRec*    Instr;
  824.  
  825.         CheckPtrExistence(InstrList);
  826.         ERROR((Index < 0) || (Index >= InstrListHowMany(InstrList)),
  827.             PRERR(ForceAbort,"InstrListGetIndexedInstr:  index out of range"));
  828.         Instr = (InstrObjectRec*)ArrayGetElement(InstrList->InstrArray,Index);
  829.         CheckPtrExistence(Instr);
  830.         return Instr;
  831.     }
  832.